package com.skydonkey.controller;


import com.auth0.jwt.JWT;
import com.skydonkey.pojo.po.Account;
import com.skydonkey.pojo.po.AccountInfo;
import com.skydonkey.pojo.vo.*;
import com.skydonkey.service.AccountInfoService;
import com.skydonkey.service.AccountService;
import com.skydonkey.utils.*;
import com.skydonkey.validator.AccountValidator;
import com.skydonkey.validator.CommonValidator;
import com.skydonkey.verify.PassToken;
import com.skydonkey.verify.VerifyToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.UUID;


@RestController
@RequestMapping(path = "/account")
public class AccountController {

    private static final Logger log = LoggerFactory.getLogger(AccountController.class);

    @Autowired
    QiniuUtils qiniuUtils;

    @Autowired
    RedisUtils redisUtils;

    @Autowired
    AccountService accountService;

    @Autowired
    AccountInfoService accountInfoService;

    // 创建账号接口
    @PassToken
    @RequestMapping(path = "/create", method = RequestMethod.POST)
    public Result<CreateAccountResp> createAccount(@RequestBody LoginAccountReq loginAccountReq) {
        return createAccount(loginAccountReq.getUsername(), loginAccountReq.getNickname(), loginAccountReq.getPassword());
    }


    // 创建账号接口 - 测试
    @RequestMapping(path = "/create/{username}/{nickname}/{password}", method = RequestMethod.GET)
    @PassToken
    @Transactional
    public Result<CreateAccountResp> createAccount(@PathVariable String username,
                                                   @PathVariable String nickname,
                                                   @PathVariable String password) {

        // 校验参数是否输入正确
        if ("".equals(username) || username == null || "".equals(password) || password == null) {
            Result<CreateAccountResp> result = new Result<>(ResultEnum.INVALID_ARGS);
            result.setMsg("用户名或密码为空");
            return result;
        }

        // 校验用户名是否存在
        Account foundAccount = accountService.findByUsername(username);
        if (foundAccount != null) {
            Result<CreateAccountResp> result = new Result<>(ResultEnum.INVALID_ARGS);
            result.setMsg("用户名已存在");
            return result;
        }

        // 生成随机用户名
        if (nickname == null || "".equals(nickname)) {
            Account acc = null;
            do {
                nickname = "用户" + UUID.randomUUID().toString().substring(0, 6);
                acc = accountService.findByUsername(username);
            } while (acc != null);
        }

        Account account = new Account();
        account.setUsername(username);
        account.setNickname(nickname);
        // 对密码进行加密
        try {
            String pwd = SkydonkeyUtils.encodePassword(password, username);
            account.setPassword(pwd);
        } catch (Exception e) {
            return new Result<>(ResultEnum.INTERNAL_ERROR);
        }
        // 存入数据库
        boolean success = accountService.createAccount(account);
        if (!success) {
            return new Result<>(ResultEnum.INTERNAL_ERROR);
        }

        // 生成token返回前端
        Account acc = accountService.findByUsername(username);
        String token = JWTUtils.generateToken(acc);

        // 创建账号信息相关默认值
        AccountInfo accountInfo = new AccountInfo();
        accountInfo.setUid(acc.getUid());
        accountInfoService.addAccountInfo(accountInfo);
        CreateAccountResp resp = new CreateAccountResp();
        resp.setToken(token);

        return new Result<>(ResultEnum.SUCCESS, resp);
    }


    @PassToken
    @RequestMapping(path = "/login", method = RequestMethod.POST)
    public Result<LoginAccountResp> loginAccount(@RequestBody @Nullable LoginAccountReq loginAccountReq) {
        if (loginAccountReq == null) {
            return new Result<>(ResultEnum.INVALID_ARGS);
        }
        return loginAccount(loginAccountReq.getUsername(), loginAccountReq.getPassword());
    }

    // 登录账号接口 - 测试
    @PassToken
    @RequestMapping(path = "/login/{username}/{password}", method = RequestMethod.GET)
    public Result<LoginAccountResp> loginAccount(@PathVariable String username,
                                                 @PathVariable String password) {
        Account account = accountService.findByUsername(username);
        if (account == null) {
            return new Result<>(ResultEnum.UNKNOWN_USER);
        }
        String pwd = SkydonkeyUtils.encodePassword(password, username);
        if (!account.getPassword().equals(pwd)) {
            return new Result<>(ResultEnum.LOGIN_FAILED);
        }
        LoginAccountResp resp = new LoginAccountResp();
        resp.setToken(JWTUtils.generateToken(account));
        return Result.success(resp);
    }


    // 获取用户信息
    @VerifyToken
    @RequestMapping(path = "/info", method = RequestMethod.GET)
    public Result<AccountInfoResp> getUserInfo(
            HttpServletRequest request) {

        String uidStr = JWTUtils.getUidFromRequest(request);
        if (uidStr == null || "".equals(uidStr)) {
            return new Result<>(ResultEnum.UNKNOWN_USER);
        }
        Long uid = Long.parseLong(uidStr);
        Account account = accountService.findByUid(uid);
        if (account == null) {
            return new Result<>(ResultEnum.UNKNOWN_USER);
        }
        AccountInfo accountInfo = accountInfoService.getAccountInfo(uid);
        if (accountInfo == null) {
            return new Result<>(ResultEnum.UNKNOWN_USER);
        }
        AccountInfoResp resp = new AccountInfoResp();
        BeanUtils.copyProperties(account, resp);
        BeanUtils.copyProperties(accountInfo, resp);
        log.info("getUserInfo: " + resp);
        return Result.success(resp);
    }

    //刷新token
    @VerifyToken
    @RequestMapping(path = "/refresh-token", method = RequestMethod.GET)
    public Result<LoginAccountResp> refreshToken(HttpServletRequest httpServletRequest) {
        String token = httpServletRequest.getHeader("Authorization");
        String id = JWT.decode(token).getAudience().get(0);
        Account account = accountService.findByUid(Long.parseLong(id));
        if (account == null) {
            return new Result<>(ResultEnum.UNKNOWN_USER);
        }
        LoginAccountResp resp = new LoginAccountResp();
        resp.setToken(JWTUtils.generateToken(account));
        return Result.success(resp);
    }

    //设置用户头像
    @VerifyToken
    @RequestMapping(path = "/avator/upload", method = RequestMethod.POST)
    public Result<UploadFileResp> uploadVideo(
            @RequestParam("file") MultipartFile file) throws IOException {
        String originName = file.getOriginalFilename();
        log.info("filename: " + originName);
        log.info("file size: " + file.getBytes().length);
        // 重新生成一个新的文件名, 用uuid
        String[] split = originName.split("\\.");
        String suffix = split[split.length - 1];
        String key = UUID.randomUUID() + "." + suffix;
        String downloadUrl = qiniuUtils.uploadFile(key, file.getBytes());
        UploadFileResp uploadVideoResp = new UploadFileResp()
                .setKey(key)
                .setUrl(downloadUrl);
        return new Result<>(ResultEnum.SUCCESS, uploadVideoResp);
    }


    /**
     * 更新账户信息
     */
    @VerifyToken
    @RequestMapping(path = "/info/update", method = RequestMethod.POST)
    public Result<AccountInfoResp> updateAccountInfo(@RequestBody AccountInfoReq req) {

        AccountInfoResp resp = accountInfoService.updateAccountInfo(req);
        return Result.success(resp);
    }


    /**
     * 查询一个视频的发布者的一些简单信息
     */
    @PassToken
    @RequestMapping(path = "/info/simple/{uid}", method = RequestMethod.GET)
    public Result<SimpleVideoUserInfoResp> getSimpleVideoUserInfo(@PathVariable("uid") Long uid) {
        if (uid == null) {
            return Result.failed(null);
        }
        SimpleVideoUserInfoResp resp = accountInfoService.getSimpleVideoUserInfo(uid);
        return resp != null ? Result.success(resp) : Result.failed(null);
    }


    @PassToken
    @RequestMapping(path = "/info/comment/get/{uid}", method = RequestMethod.GET)
    public Result<SimpleVideoUserInfoResp> getAccountInfoInComment(@PathVariable("uid") Long uid) {
        SimpleVideoUserInfoResp resp = new SimpleVideoUserInfoResp();
        SimpleVideoUserInfoResp simpleVideoUserInfo = accountInfoService.getSimpleVideoUserInfo(uid);
        BeanUtils.copyProperties(simpleVideoUserInfo, resp);
        return Result.success(resp);
    }


    @VerifyToken
    @RequestMapping(path = "/follow/add", method = RequestMethod.POST)
    public Result<AddFollowResp> addFollow(
            HttpServletRequest request,
            @RequestBody AddFollowReq req
    ) {
        if (CommonValidator.hasEmptyFields(req) || !AccountValidator.isValid(request, req.getUid())) {
            return Result.failed(null);
        }
        AddFollowResp resp = accountInfoService.addFollow(req);
        return Result.success(resp);
    }

    @VerifyToken
    @RequestMapping(path = "/follow/del", method = RequestMethod.POST)
    public Result<DelFollowResp> delFollow(
            HttpServletRequest request,
            @RequestBody DelFollowReq req
    ) {
        if (CommonValidator.hasEmptyFields(req) || !AccountValidator.isValid(request, req.getUid())) {
            return Result.failed(null);
        }
        DelFollowResp resp = accountInfoService.delFollow(req);
        return Result.success(resp);
    }


    //获取我关注的人的列表
    @VerifyToken
    @RequestMapping(path = "/following", method = RequestMethod.POST)
    public Result<GetFollowingResp> getFollowing(
            HttpServletRequest request,
            @RequestBody GetFollowingReq req
    ){
        if (CommonValidator.hasEmptyFields(req) || !AccountValidator.isValid(request, req.getUid())) {
            return Result.failed(null);
        }
        GetFollowingResp resp = accountInfoService.getFollows(req);
        return Result.success(resp);
    }


    //获取关注我的人的列表
    @VerifyToken
    @RequestMapping(path = "/followers", method = RequestMethod.POST)
    public Result<GetFollowerResp> getFollower(
            HttpServletRequest request,
            @RequestBody GetFollowerReq req
    ){
        if (CommonValidator.hasEmptyFields(req) || !AccountValidator.isValid(request, req.getUid())) {
            return Result.failed(null);
        }
        GetFollowerResp resp = accountInfoService.getFollowers(req);
        return Result.success(resp);
    }
}



